package ws.jdbc.concurrent.driver.sqlserver.tds;

import java.io.IOException;
import java.nio.ByteBuffer;
import ws.jdbc.concurrent._development.DevMode;

/**
 * Handles the {@code ENVCHANGE} token reading process.
 *
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
class InfoTokenReader extends TokenReader {

  /**
   * The info number.
   */
  private int infoNumber;
  /**
   * The error state, used as a modifier to the info Number.
   */
  protected byte errorState;
  /**
   * The class (severity) of the error.
   * A class of less than 10 indicates an informational message.
   */
  private byte errorClass;
  /**
   * The message text length and message text using US_VARCHAR format.
   */
  protected String msgText;
  /**
   * The server name length and server name using B_VARCHAR format.
   */
  private String serverName;
  /**
   * The stored procedure name length and stored procedure name using B_VARCHAR format.
   */
  private String procName;
  /**
   * The line number in the SQL command batch or stored procedure that caused the error.
   * Line numbers begin at 1; therefore, if the line number stream not applicable to the message
   * as determined by the upper layer, the value of LineNumber will be 0.
   */
  private int lineNumber;

  /**
   * Create a new reader instance.
   *
   * @param stream data input stream to read the token from.
   */
  InfoTokenReader(final ByteBuffer stream) {
    super(stream);
  }

  /**
   * Read one {@code INFO} token.
   *
   * @return number of bytes read.
   *
   * @throws IOException if an error occurs while reading from the data input stream.
   */
  @Override
  int read() throws IOException {
    if (DevMode.concurrent_driver_sqlserver_tds) {
      DevMode.printlog(null);
    }
    // Length (USHORT)
    tokenLength = stream.getShort();
    // Number (LONG - 4 bytes)
    infoNumber = stream.getInt();
    // State (BYTE)
    errorState = stream.get();
    // Class (BYTE)
    errorClass = stream.get();
    // MsgText (US_VARCHAR)
    msgText = vldsReader.readUSVarChar().getData();
    // ServerName (B_VARCHAR)
    serverName = vldsReader.readBVarChar().getData();
    // ProcName (B_VARCHAR)
    procName = vldsReader.readBVarChar().getData();
    // LineNumber (ULONG - TDS 7.2)
    lineNumber = stream.getInt();

    return 12 + vldsReader.getBytesRead();
  }

  /**
   * Token as a {@code String}.
   *
   * @return token fields as a {@code String}.
   */
  @Override
  public String toString() {
    return "InfoTokenReader{"
            + "\n  infoNumber=" + infoNumber
            + "\n  errorState=" + errorState
            + "\n  errorClass=" + errorClass
            + "\n  msgText=" + msgText
            + "\n  serverName=" + serverName
            + "\n  procName=" + procName
            + "\n  lineNumber=" + lineNumber
            + "\n}\n";
  }
}
